﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Web;
using System.Web.Hosting;
using Ue.Utility;

namespace Ue.Web
{
    public class VirtualPathProvider : IVirtualPathProvider
    {
        #region IVirtualPathProvider 成员

        public string Combine(params string[] paths)
        {
            if (paths == null || paths.Length == 0)
            {
                throw new ArgumentNullException("paths");
            }

            var resultPath = paths[0];
            for (int i = 1; i < paths.Length; i++)
            {
                resultPath = Path.Combine(resultPath, paths[i]);
            }

            return PathUtility.PhysicsPathSeparatorCharConvertToVirtualPathSeparatorChar(resultPath);
        }

        public string ToAppRelative(string virtualPath)
        {
            if (VirtualPathHelper.IsMalformedVirtualPath(virtualPath))
                return null;

            try
            {
                string result = VirtualPathUtility.ToAppRelative(virtualPath);

                if (!result.StartsWith("~/"))
                {
                    return null;
                }
                return result;
            }
            catch (Exception)
            {
                return null;
            }
        }

        public string MapPath(string virtualPath)
        {
            return HostingEnvironment.MapPath(virtualPath);
        }

        public bool FileExists(string virtualPath)
        {
            return HostingEnvironment.VirtualPathProvider.FileExists(virtualPath);
        }

        public bool TryFileExists(string virtualPath)
        {
            if (VirtualPathHelper.IsMalformedVirtualPath(virtualPath))
                return false;

            try
            {
                return FileExists(virtualPath);
            }
            catch (Exception)
            {
                return false;
            }
        }

        public Stream OpenFile(string virtualPath)
        {
            return HostingEnvironment.VirtualPathProvider.GetFile(virtualPath).Open();
        }

        public StreamWriter CreateText(string virtualPath)
        {
            return File.CreateText(this.MapPath(virtualPath));
        }

        public Stream CreateFile(string virtualPath)
        {
            return File.Create(this.MapPath(virtualPath));
        }

        public DateTime GetFileLastWriteTimeUtc(string virtualPath)
        {
            return File.GetLastWriteTimeUtc(this.MapPath(virtualPath));
        }

        public string GetFileHash(string virtualPath)
        {
            return this.GetFileHash(virtualPath, new[] { virtualPath });
        }

        public string GetFileHash(string virtualPath, IEnumerable<string> dependencies)
        {
            return HostingEnvironment.VirtualPathProvider.GetFileHash(virtualPath, dependencies);
        }

        public bool DirectoryExists(string virtualPath)
        {
            return HostingEnvironment.VirtualPathProvider.DirectoryExists(virtualPath);
        }

        public void CreateDirectory(string virtualDir)
        {
            Directory.CreateDirectory(this.MapPath(virtualDir));
        }

        public string GetDirectoryName(string virtualDir)
        {
            return PathUtility.PhysicsPathSeparatorCharConvertToVirtualPathSeparatorChar(Path.GetDirectoryName(virtualDir));
        }

        public IEnumerable<string> ListFiles(string virtualDir)
        {
            return HostingEnvironment
                .VirtualPathProvider
                .GetDirectory(virtualDir)
                .Files
                .OfType<VirtualFile>()
                .Select(f => VirtualPathUtility.ToAppRelative(f.VirtualPath));
        }

        public IEnumerable<string> ListDirectories(string virtualDir)
        {
            return HostingEnvironment
                .VirtualPathProvider
                .GetDirectory(virtualDir)
                .Directories
                .OfType<VirtualFile>()
                .Select(f => VirtualPathUtility.ToAppRelative(f.VirtualPath));
        }

        #endregion
    }
}
